package org.ponly.uno4j.support;

import org.ponly.common.util.FileUtils;
import org.ponly.common.util.HttpUtils;
import org.ponly.common.util.IOUtils;
import org.ponly.uno4j.core.UnoClient;
import org.ponly.uno4j.core.impl.EmbeddedUnoClientImpl;
import org.ponly.web.servlet.ResourceServlet;
import org.ponly.web.util.Multipart;
import org.ponly.web.util.WebUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;
import java.util.Map;

/**
 * 简单的查看器
 * <p/>
 * 使用:
 * <br/>
 * <code>
 * <pre>
 *   <servlet>
 *      <servlet-name>live-view</servlet-name>
 *      <servlet-class>org.ponly.uno4j.support.LiveViewServlet</servlet-class>
 *      <init-param>
 *         <param-name>upload</param-name>
 *         <param-value>true</param-value>
 *      </init-param>
 *   </servlet>
 *   <servlet-mapping>
 *      <servlet-name>live-view</servlet-name>
 *      <url-pattern>/live/*</url-pattern>
 *   </servlet-mapping>
 * </pre>
 * </code>
 * <br/>
 * visit: <br/>
 * single mode: schema://host:port/live/fp.html?url=swf_url <br/>
 * split mode: schema://host:port/live/fp.html?url=swf-{totalPages}-%.swf
 *
 * @author vacoor
 */
public class LiveViewServlet extends ResourceServlet {
    private D2sService d2s;

    public LiveViewServlet() {
        super("support/web/flexpaper");
    }

    @Override
    public void init() throws ServletException {
        super.init();

        // 启用 upload
        if("true".equalsIgnoreCase(getInitParameter("upload"))) {
            UnoClient unoClient = new EmbeddedUnoClientImpl("socket", 8888, 1).start();
            d2s = new SimpleD2sServiceImpl(unoClient, 10);
        }
    }

    @Override
    public void destroy() {
        super.destroy();
        if (null != d2s) {
            d2s.shutdown();
        }
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 没有启用上传或不是上传请求
        if (null == d2s || !Multipart.isMultipartRequest(request)) {
            super.service(request, response);
        } else {
            doUpload(request, response);
        }
    }

    /* ******************************************************************
     *                         上传 DEBUG 方法
     * ******************************************************************/

    /**
     * 执行文件上传及转换
     *
     * @param req 上传请求
     * @param resp 上传响应
     * @throws ServletException
     * @throws IOException
     */
    protected void doUpload(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (!Multipart.isMultipartRequest(req)) {
            resp.sendError(400);
            return;
        }

        final File tempDir = WebUtils.getTempDir(getServletContext());
        final File targetDir = new File(tempDir, "uno4j");

        if (!targetDir.exists() && !targetDir.mkdirs()) {
            throw new IllegalStateException("Can't mkdir " + targetDir);
        }

        final String[] split = new String[1];
        final File[] files = new File[1];
        Multipart.parse(req, new Multipart.Handler() {
            @Override
            public void onParameter(String name, String value, Map<String, String> multipartHeaders) {
                if ("split".equalsIgnoreCase(name)) {
                    split[0] = value;
                }
            }

            @Override
            public void onPart(String name, String filename, InputStream multipartIn, Map<String, String> multipartHeaders) throws IOException {
                if (null == files[0]) {
                    files[0] = new File(targetDir, filename);
                    FileOutputStream fout = new FileOutputStream(files[0]);

                    IOUtils.flow(multipartIn, fout, true, true);
                }
            }
        });

        if (null == files[0]) {
            resp.sendError(400);
            return;
        }

        // 提交转换任务
        boolean sp = "1".equals(split[0]);
        File src = files[0];
        File target = new File(src.getAbsolutePath() + (sp ? "-?-%.swf" : ".swf"));
        D2sTask task = D2sTask.create(src.getAbsolutePath(), src.getAbsolutePath(), target.getAbsolutePath());
        d2s.submit(task);

        try {
            long start = new Date().getTime();
            while (null == task.getSwf()) {
                long time = new Date().getTime();
                if (time - start > 5 * 60 * 1000) {
                    break;
                }
                Thread.sleep(1000);
            }

            // 等待完成
            String path = req.getServletPath();
            path = WebUtils.getUrlWithoutApplication(req, path.endsWith("/") ? path + "snapshot" : path + "/snapshot");
            String swf = task.getSwf();
            if (null != swf) {
                swf = FileUtils.getNameWithoutExtension(swf);
            } else {
                swf = src.getName();
            }
            swf = path + "?f=" + HttpUtils.encode(swf).replace("+", "%20");

            String url = "fp.html?swf=" + swf;
            resp.sendRedirect(url);
        } catch (Exception ex) {
            throw new ServletException(ex);
        }
    }

    @Override
    protected void handleRequest(String path, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 如果启用了测试上传且是读取文件请求
        if (null != d2s && "/snapshot".equals(path)) {
            final String filename = req.getParameter("f");
            final File tempDir = WebUtils.getTempDir(getServletContext());
            final File target = new File(tempDir, "uno4j/" + filename + ".swf");

            if (!target.exists() || !target.canRead()) {
                resp.sendError(400);
                return;
            }
            IOUtils.flow(new FileInputStream(target), resp.getOutputStream(), true, true);
        } else {
            resp.sendError(404);
        }
    }
}
